home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9207.ZIP / AVK.ASC < prev    next >
Text File  |  1992-06-15  |  23KB  |  754 lines

  1. _CAPTURING DIGITAL VIDEO USING DVI_
  2. by James L. Green
  3.  
  4. [LISTING ONE]
  5.  
  6. //--- AvkCapt.h  Copyright Intel Corp. 1991, 1992, All Rights Reserved --- 
  7.  
  8. #include "avkapi.h"
  9.  
  10. // File name for the RTV 2.0 VSH data file (from avkalg.h)
  11. #define VSHFILE_NAME    AVK_RTV_20_ENCODE_DATA_NAME
  12.  
  13. // A couple of shorthand AVK #defines for convenience
  14. #define OK      AVK_ERR_OK
  15. #define NOW     AVK_TIME_IMMEDIATE
  16. #define HNULL       ((HAVK)0)
  17.  
  18. // Values for capturing
  19. #define AUD_SAMPLE_RATE (U32)33075
  20. #define FRAME_RATE  (U32)33367
  21.  
  22. // Size of Capture Data Buffers
  23. #define VID_BUF_SIZE    (256L * 1024L)
  24. #define VID_BUF_GRAN    ( 64L * 1024L)
  25. #define AUD_BUF_SIZE    (128L * 1024L)
  26. #define AUD_BUF_GRAN    ( 16L * 1024L)
  27. #define HOST_BUF_SIZE   32768U
  28.  
  29. // Maximum number of iterations of the capture loop
  30. // before we are forced back to the main message loop
  31. #define CAPTURE_LOOPS   10
  32.  
  33. // ID value for the capture Windows timer
  34. #define TIMER_ID    1
  35.  
  36. // Number of milliseconds between timer ticks
  37. #define TIMER_INTERVAL  500
  38.  
  39. // States for the capture engine
  40. #define ST_UNINITIALIZED    0
  41. #define ST_INITIALIZED      1
  42. #define ST_MONITORING       2
  43. #define ST_CAPTURING        3
  44.  
  45. // Control structure for the current view
  46. typedef struct tagVIEW
  47. {
  48.     HAVK    hView;          // AVK View handle
  49.     HAVK    hConnDigi2Strm;     // Digitizer to Video Stream connector
  50.     HAVK    hConnStrm2View;     // Video Stream to View connector
  51.     BOOL    bConnEnabled;       // TRUE if the connector is enabled
  52.     WORD    DviMonitorSync;     // DviMonitorSync value from AVK.INI
  53.     I16 cxView;         // View's x resolution
  54.     I16 cyView;         // View's y resolution
  55.     double  xDelta;         // used to convert screen
  56.     double  yDelta;         //  coords to view
  57.     I16 cxScreen;       // physical screen's x resolution
  58.     I16 cyScreen;       // physical screen's y resolution
  59.     U16 VidType;        // View's video type
  60.     U16 BmFmt;          // View's bitmap format
  61.     BOOL    bIsKeyed;       // TRUE if the View is keyed
  62.     BOX SrcBox;         // connector's source rectangle
  63.     BOX DstBox;         // connector's destination rectangle
  64. } VIEW;
  65.  
  66. // Control structure for capture buffers
  67. typedef struct tagCAPT
  68. {
  69.     HAVK        hGrpBuf;    // group buffer handle
  70.     HAVK        hStrm;      // stream handle
  71.     char far    *pBufHead;  // host RAM I/O buffer
  72.     char far    *pBufCurr;  // current position in host I/O buffer
  73.     U32     BufDataCnt; // amount of data in host I/O buffer
  74. } CAPT;
  75.  
  76. // Structure for storing sync resolutions. The sync table
  77. // will be an array of VIDEO_SYNC structures called Syncs[].
  78. typedef struct tagVIDEO_SYNC
  79. {
  80.     WORD    xResRTV;    // RTV capture x resolution
  81.     WORD    xResVid;    // Video stream premonitor x resolution
  82.     WORD    yResVid;    // Video stream premonitor y resolution
  83.     WORD    FrameRate;
  84.     WORD    PixelAspect;
  85. } VIDEO_SYNC;
  86.  
  87. // These sync values are subscripts into a table of VIDEO_SYNC structures
  88. #define SYNC_NTSC   0
  89. #define SYNC_PAL    1
  90.  
  91.  
  92. [LISTING TWO]
  93.  
  94. // ---- Windows AVK Capture Program - Create Recorder  ----------------
  95. // ---- Copyright Intel Corp. 1991, 1992, All Rights Reserved ---------
  96.  
  97. extern HWND     hwndMain;
  98. extern VIDEO_SYNC   Syncs[];
  99.  
  100. // Local variables
  101. static WORD State = ST_UNINITIALIZED; // current state of capture engine
  102. WORD        CaptureSync = SYNC_NTSC;  // default to NTSC 
  103. char far    *pVshBuf    = NULL;   // buffer for reading VSH data.
  104. U32     VshSize;    // size of the VSH data
  105. VIEW        View;       // view control structure
  106. AVIO_SUM_HDR    Avio;       // master control struct for AVSS file I/O
  107. CAPT        Vid;        // video capture control structure
  108. CAPT        Aud;        // audio capture control structure
  109. I16     AvkRet;     // general AVK return code variable
  110.  
  111. // RTV 2.0 encoding arguments
  112. AVK_RTV_20_ENCODE_ARGS Rtv20Args =
  113. {
  114.     12,         // argument count
  115.     AVK_RTV_2_0,        // algorithm size
  116.     0,0,            // x,y coords of origin
  117.     128, 240,       // xLength, yLength 
  118.     3,          // still period
  119.     0, 0,           // bytes,lines
  120.     AVK_RTV_20_PREFILTER | AVK_RTV_20_ASPECT_25,    // flags
  121.     0, 0            // quantization values
  122. };
  123.  
  124. // AVK handles
  125. HAVK    hAvk    = (HAVK)0;
  126. HAVK    hDev    = (HAVK)0;
  127. HAVK    hGrp    = (HAVK)0;
  128.  
  129. // Create AVK session and initialize the device
  130. BOOL InitAvk()
  131. {
  132.     if (!IsState(ST_UNINITIALIZED))
  133.         return TRUE;
  134.  
  135.     // Start an AVK session with messaging
  136.     if ((AvkRet = AvkBeginMsg(hwndMain, &hAvk,
  137.         AVK_SESSION_DEFAULT)) != OK)
  138.         return DispAvkErr(AvkRet, "AvkBeginMsg");
  139.     
  140.     // Open the ActionMedia(R) device
  141.     if ((AvkRet = AvkDeviceOpen(hAvk, 0,
  142.         AVK_DEV_OPEN_EXCLUSIVE, &hDev)) != OK)
  143.         return DispAvkErr(AvkRet, "AvkDeviceOpen");
  144.  
  145.     // Get the capture sync by calling AvkDeviceVideoIn()
  146.     if ((AvkRet = AvkDeviceVideoIn(hDev, AVK_CONN_DIGITIZER)) != OK)
  147.         return DispAvkErr(AvkRet, "AvkDeviceVideoIn");
  148.  
  149.     return TRUE;
  150. }
  151. // Check device capabilities and build the recorder
  152. BOOL CreateAvkResources(WORD NewCaptureSync)
  153. {
  154.     switch (NewCaptureSync)
  155.     {
  156.         case AVK_SYNC_NTSC: CaptureSync = SYNC_NTSC;    break;
  157.         case AVK_SYNC_PAL:  CaptureSync = SYNC_PAL;     break;
  158.     }
  159.  
  160.     // Get the AVK device capabilities from AVK.INI
  161.     if (!GetDevCaps(&View))
  162.         return FALSE;
  163.  
  164.     if (!CreateView(&View))
  165.          return FALSE;
  166.  
  167.     // The Vsh file contains data used in compressing
  168.     // the incoming motion video into an RTV 2.0 file.
  169.     if (!LoadVshFile())
  170.         return FALSE;
  171.  
  172.     if (!CreateCaptureGroup())
  173.         return FALSE;
  174.  
  175.     ToState(ST_INITIALIZED);
  176.  
  177.     return TRUE;
  178. }
  179. // Get the device capabilities from AVK
  180. BOOL GetDevCaps(VIEW *pView)
  181. {
  182.     DVICAPS DevCaps;
  183.  
  184.     // Get the physical screen resolution from the system
  185.     pView->cxScreen = GetSystemMetrics(SM_CXSCREEN);
  186.     pView->cyScreen = GetSystemMetrics(SM_CYSCREEN);
  187.  
  188.     // Get the AVK device capabilities which were set in AVK.INI
  189.     if ((AvkRet = AvkGetDevCaps(0, sizeof(DevCaps), &DevCaps)) != OK)
  190.         return DispAvkErr(AvkRet, "AvkGetDevCaps");
  191.  
  192.     if (DevCaps.DigitizerRevLevel == 0)
  193.         return DispErr("GetDevCaps", 
  194.           "Digitizer needed for capturing - check AVK.INI");
  195.  
  196.     if (DevCaps.DviMonitorSync & 0x10)      // VGA
  197.     {
  198.         pView->cxView   = 256;
  199.         pView->cyView   = 240;
  200.         pView->VidType = AVK_VID_VGA_KEYED;
  201.         pView->bIsKeyed = TRUE;
  202.     }
  203.     else if (DevCaps.DviMonitorSync & 0x100)    // XGA
  204.     {
  205.         pView->cxView   =  256;
  206.         pView->cyView   =  192;
  207.         pView->VidType = AVK_VID_XGA_KEYED;
  208.         pView->bIsKeyed = TRUE;
  209.     }
  210.     else if (DevCaps.DviMonitorSync & 0x02)     // PAL
  211.     {
  212.         pView->cxView = 306;
  213.         pView->cyView = 288;
  214.         pView->VidType = AVK_VID_PAL;
  215.     }
  216.     else if (DevCaps.DviMonitorSync & 0x01)     // NTSC
  217.     {
  218.         pView->cxView = 256;
  219.         pView->cyView = 240;
  220.         pView->VidType = AVK_VID_NTSC;
  221.     }
  222.     else
  223.         return DispErr("GetDevCaps", "Invalid monitor sync");
  224.  
  225.     // Calculate Screen-To-AVK coordinate conversion deltas.
  226.     pView->xDelta = (double)pView->cxView / (double)pView->cxScreen;
  227.     pView->yDelta = (double)pView->cyView / (double)pView->cyScreen;
  228.  
  229.     return TRUE;
  230. }
  231. // Create and display an AVK View
  232. static BOOL CreateView(VIEW *pView)
  233. {
  234.     if ((AvkRet = AvkViewCreate(hDev, pView->cxView, pView->cyView,
  235.         AVK_YUV9, pView->VidType,  &pView->hView)) != OK)
  236.         return DispAvkErr(AvkRet, "AvkViewCreate");
  237.     
  238.     // Display the View
  239.     if ((AvkRet = AvkViewDisplay(hDev, pView->hView, NOW, 
  240.       AVK_VIEW_DISPLAY_DEFAULT)) != OK)
  241.         return DispAvkErr(AvkRet, "AvkViewDisplay");
  242.  
  243.     // Set the destination box for the stream-to-view connector
  244.     if (!SetDstBox(hwndMain))
  245.         return FALSE;
  246.  
  247.     return TRUE;
  248. }
  249. // Set the destination box for the stream-to-view connector
  250. BOOL SetDstBox(HWND hwndMain)
  251. {
  252.     RECT    WinRect;
  253.     BOX NewDstBox;
  254.     
  255.     GetClientRect(hwndMain, (LPRECT)&WinRect);
  256.     ClientToScreen(hwndMain, (LPPOINT)&WinRect);
  257.     WinRect.right = WinRect.left + (View.cxScreen >> 1) - 1;
  258.     WinRect.bottom = WinRect.top + (View.cyScreen >> 1) -1;
  259.     WinRect2AvkBox(&WinRect, &NewDstBox, &View);
  260.  
  261.     if (View.hConnStrm2View)
  262.     {
  263.         if ((AvkRet = AvkConnHide(View.hConnStrm2View, NOW)) != OK)
  264.             return DispAvkErr(AvkRet, "AvkConnHide");
  265.  
  266.         if ((AvkRet = AvkViewCleanRect(View.hView,
  267.             &View.DstBox)) != OK)
  268.             return DispAvkErr(AvkRet, "AvkViewCleanRect");
  269.  
  270.         // Reset the destination of the connector to our new box
  271.         if ((AvkRet = AvkConnModSrcDst(View.hConnStrm2View, NULL,
  272.             &NewDstBox, NOW)) != OK)
  273.             return DispAvkErr(AvkRet, "AvkConnModSrcDst");
  274.  
  275.         if ((AvkRet = AvkConnEnable(View.hConnStrm2View, NOW)) != OK)
  276.             return DispAvkErr(AvkRet, "AvkConnEnable");
  277.  
  278.     }
  279.  
  280.     // Copy new destination coords into the view's destination box
  281.     COPYBOX(&View.DstBox, &NewDstBox);
  282.  
  283.     return TRUE;
  284. }
  285. // Get the standard VSH file that comes with AVK
  286. static BOOL LoadVshFile()
  287. {
  288.     int     fhVsh;
  289.     OFSTRUCT    Of;
  290.  
  291.     // Open the VSH file
  292.     if ((fhVsh = OpenFile(VSHFILE_NAME, &Of, OF_READ)) == -1)
  293.         return DispErr("LoadVshFile",
  294.             "Unable to find the file KE080200.VSH");
  295.     
  296.     VshSize = filelength(fhVsh);
  297.  
  298.     // Range check - Reject if VshSize == 0 or VshSize > 65535L
  299.     if (!VshSize || VshSize & 0xffff0000)
  300.         return DispErr("LoadVshFile", "VSH file too large to load");
  301.  
  302.     // Allocate a buffer to stash the VSH file.
  303.     if ((pVshBuf = MemAlloc((WORD)VshSize)) == NULL)
  304.         return DispErr("LoadVshFile",
  305.             "Unable to allocate VSH file buffer");
  306.  
  307.     // Read the VSH data from the file
  308.     if (_lread(fhVsh, pVshBuf, (WORD)VshSize) != (WORD)VshSize)
  309.         return DispErr("LoadVshFile", "Unable to read VSH file");
  310.  
  311.     return TRUE;
  312. }
  313. // Create Capture Group and resources needed for premonitoring
  314. static BOOL CreateCaptureGroup()
  315. {
  316.     if ((AvkRet = AvkGrpCreate(hDev, &hGrp)) != OK)
  317.         return DispAvkErr(AvkRet, "AvkGrpCreate");
  318.  
  319.     if ((AvkRet = AvkGrpBufCreate(hGrp, AVK_BUF_CAPTURE, VID_BUF_SIZE, 
  320.         VID_BUF_GRAN, 1, &Vid.hGrpBuf)) != OK)
  321.         return DispAvkErr(AvkRet, "AvkGrpBufCreate");
  322.  
  323.     if ((AvkRet = AvkGrpBufCreate(hGrp, AVK_BUF_CAPTURE, AUD_BUF_SIZE, 
  324.         AUD_BUF_GRAN, 1, &Aud.hGrpBuf)) != OK)
  325.         return DispAvkErr(AvkRet, "AvkGrpBufCreate");
  326.  
  327.     // Create host RAM I/O buffers for retrieving
  328.     // video and audio frames and initialize them.
  329.     if ((Vid.pBufHead = MemAlloc(HOST_BUF_SIZE)) == NULL
  330.      || (Aud.pBufHead = MemAlloc(HOST_BUF_SIZE)) == NULL)
  331.         return DispErr("CreateCaptureGroup", 
  332.           "Unable to allocate host RAM I/O buffer");
  333.     Vid.BufDataCnt = (U32)0;
  334.     Aud.BufDataCnt = (U32)0;
  335.  
  336.     if (!CreateVideoStream())
  337.         return FALSE;
  338.  
  339.     if (!CreateAudioStream())
  340.         return FALSE;
  341.  
  342.     if ((AvkRet = AvkGrpFlush(hGrp)) != OK)
  343.         return DispAvkErr(AvkRet, "AvkGrpFlush");
  344.  
  345.     return TRUE;
  346. }
  347. // Create and format a video stream for the video capture buffer
  348. static BOOL CreateVideoStream()
  349. {
  350.     if ((AvkRet = AvkVidStrmCreate(Vid.hGrpBuf, 0, &Vid.hStrm)) != OK)
  351.         return DispAvkErr(AvkRet, "AvkVidStrmCreate");
  352.  
  353.     // Format the video stream
  354.     Rtv20Args.xLen = Syncs[CaptureSync].xResRTV;
  355.     Rtv20Args.yLen = Syncs[CaptureSync].yResVid;
  356.     if ((AvkRet = AvkVidStrmFormat(Vid.hStrm, 
  357.         6, 
  358.         Syncs[CaptureSync].xResVid,
  359.         Syncs[CaptureSync].yResVid,
  360.         AVK_YUV9, 
  361.         Syncs[CaptureSync].FrameRate,
  362.         AVK_RTV_2_0, 
  363.         &Rtv20Args, sizeof(Rtv20Args), sizeof(Rtv20Args),
  364.         pVshBuf, VshSize, 64L * 1024L)) != OK)
  365.         return DispAvkErr(AvkRet, "AvkVidStrmFormat");
  366.  
  367.     // Free the VSH buffer
  368.     MemFree(pVshBuf);
  369.  
  370.     // Create a connector from the digitizer to the video stream
  371.     if ((AvkRet = AvkConnCreate(AVK_CONN_DIGITIZER, NULL, Vid.hStrm,
  372.         NULL, 0, &View.hConnDigi2Strm)) != OK)
  373.         return DispAvkErr(AvkRet,
  374.             "AvkConnCreate(Digitizer to Stream)");
  375.  
  376.     // Create the connector from the video stream to the view
  377.     if ((AvkRet = AvkConnCreate(Vid.hStrm, NULL, View.hView, 
  378.       &View.DstBox, AVK_PRE_MONITOR, &View.hConnStrm2View)) != OK)
  379.         return DispAvkErr(AvkRet, "AvkConnCreate (Stream to View)");
  380.  
  381.     return TRUE;
  382. }
  383. // Create and format a audio stream for the audio capture buffer
  384. static BOOL CreateAudioStream()
  385. {
  386.     if ((AvkRet = AvkAudStrmCreate(Aud.hGrpBuf, 0, &Aud.hStrm)) != OK)
  387.         return DispAvkErr(AvkRet, "AvkAudStrmCreate");
  388.  
  389.     // Format the audio stream
  390.     if ((AvkRet = AvkAudStrmFormat(Aud.hStrm, FRAME_RATE,
  391.         AUD_SAMPLE_RATE, AVK_ADPCM4, AVK_AUD_MIX, NULL, 0, 0)) != OK)
  392.         return DispAvkErr(AvkRet, "AvkAudStrmFormat");
  393.  
  394.     return TRUE;
  395. }
  396. // Close the AVK session
  397. BOOL EndAvk()
  398. {
  399.     BOOL    Ret = TRUE;
  400.  
  401.     if (hAvk != HNULL)
  402.     {
  403.         if ((AvkRet = AvkEnd(hAvk)) != OK)
  404.         {
  405.             DispAvkErr(AvkRet, "AvkEnd");
  406.             Ret = FALSE;
  407.         }
  408.     }
  409.     if (Vid.pBufHead)
  410.     {
  411.         MemFree(Vid.pBufHead);
  412.         Vid.pBufHead = NULL;
  413.     }
  414.     if (Aud.pBufHead)
  415.     {
  416.         MemFree(Aud.pBufHead);
  417.         Aud.pBufHead = NULL;
  418.     }
  419.  
  420.     // Null out all of the AVK handles
  421.     hAvk = hDev = HNULL;
  422.     hGrp = HNULL;
  423.     Vid.hGrpBuf = Vid.hStrm = HNULL;
  424.     Aud.hGrpBuf = Aud.hStrm = HNULL;
  425.     View.hView  = HNULL;
  426.     View.hConnDigi2Strm = View.hConnStrm2View = HNULL;
  427.  
  428.     ToState(ST_UNINITIALIZED);
  429.  
  430.     return Ret;
  431. }
  432.  
  433.  
  434.  
  435.  
  436. [LISTING THREE]
  437.  
  438. //----  Windows AVK Capture Program - Recorder Control ------------
  439. //----  Copyright Intel Corp. 1991, 1992, All Rights Reserved -----
  440.  
  441. // Sets a new state and enables/disables the applicable menu options
  442. WORD ToState(WORD NewState)
  443. {
  444.     WORD    OldState;
  445.  
  446.     if (NewState == ST_CAPTURING
  447.      || NewState == ST_MONITORING
  448.      || NewState == ST_INITIALIZED
  449.      || NewState == ST_UNINITIALIZED)
  450.     {
  451.         if (State != NewState)
  452.         {
  453.             OldState = State;
  454.             State = NewState;
  455.             UpdateMenus(State);
  456.             return OldState;
  457.         }
  458.         else
  459.             return NewState;
  460.     }
  461.     return 0xffff;
  462. }
  463. // Checks whether the current state equals the caller's query state
  464. BOOL IsState(WORD QueryState)
  465. {
  466.     return State == QueryState;
  467. }
  468. // Returns the current state to the caller
  469. WORD GetState()
  470. {
  471.     return State;
  472. }
  473. // Toggle monitoring on and off based on user input
  474. BOOL ToggleMonitor(VOID)
  475. {
  476.     BOOL    bRet;
  477.     
  478.     switch (GetState())
  479.     {
  480.         case ST_INITIALIZED:    bRet = MonitorOn(); break;
  481.         case ST_MONITORING: bRet = MonitorOff();    break;
  482.         default:        bRet = TRUE;        break;
  483.     }
  484.     return bRet;
  485. }
  486. // Turn on premonitoring
  487. static BOOL MonitorOn()
  488. {
  489.     if ((AvkRet = AvkConnEnable(View.hConnDigi2Strm, NOW)) != OK
  490.      || (AvkRet = AvkConnEnable(View.hConnStrm2View, NOW)) != OK)
  491.         return DispAvkErr(AvkRet, "AvkConnEnable");
  492.  
  493.     if ((AvkRet = AvkDeviceAudioIn(hDev, AVK_AUD_CAPT_LINE_INPUT,
  494.       AVK_MONITOR_ON)) != AVK_ERR_OK)
  495.         return DispAvkErr(AvkRet, "AvkDeviceAudioIn");
  496.  
  497.     ToState(ST_MONITORING);
  498.  
  499.     SetClipTimer();
  500.  
  501.     return TRUE;
  502. }
  503. // Turn off premonitoring
  504. static BOOL MonitorOff()
  505. {
  506.     KillClipTimer();
  507.  
  508.     if ((AvkRet = AvkConnHide(View.hConnStrm2View, NOW)) != OK
  509.      || (AvkRet = AvkConnHide(View.hConnDigi2Strm, NOW)) != OK)
  510.         return DispAvkErr(AvkRet, "AvkConnHide");
  511.  
  512.     if ((AvkRet = AvkDeviceAudioIn(hDev, AVK_AUD_CAPT_LINE_INPUT,
  513.         AVK_MONITOR_OFF)) != AVK_ERR_OK)
  514.         return DispAvkErr(AvkRet, "AvkDeviceAudioIn");
  515.  
  516.     ToState(ST_INITIALIZED);
  517.  
  518.     return TRUE;
  519. }
  520. // Toggles the capture on or off
  521. BOOL ToggleCapture()
  522. {
  523.     // If no file has been opened, return
  524.     if (!bAvioFileExists)
  525.     {
  526.         DispMsg("You must open a file before you can capture");
  527.         return TRUE;
  528.     }
  529.  
  530.     switch(GetState())
  531.     {
  532.         case ST_MONITORING:
  533.             // If we are monitoring, turn on
  534.             // capture by starting the group
  535.             if ((AvkRet = AvkGrpStart(hGrp, NOW)) != OK)
  536.                 return DispAvkErr(AvkRet, "AvkGrpStart");
  537.             ToState(ST_CAPTURING);
  538.             break;
  539.         
  540.         case ST_CAPTURING:
  541.             // If we are already capturing, turn
  542.             // it off by pausing the group
  543.             if ((AvkRet = AvkGrpPause(hGrp, NOW)) != OK)
  544.                 return DispAvkErr(AvkRet, "AvkGrpPause");
  545.             break;
  546.  
  547.         default:
  548.             // Any other state, just do nothing - no error
  549.             break;
  550.     }
  551.     return TRUE;
  552. }
  553.  
  554.  
  555.  
  556.  
  557. [LISTING FOUR]
  558.  
  559. // ---- Windows AVK Capture Program - Write Captured Data to Disk ------
  560. // ---- Copyright Intel Corp. 1991, 1992, All Rights Reserved ----------
  561.  
  562. extern CAPT Aud;
  563. extern CAPT Vid;
  564. extern I16  AvkRet;
  565. extern HAVK hGrp;
  566. extern WORD CaptureSync;
  567. AVIO_SUM_HDR    Avio;
  568. BOOL        bAvioFileExists = FALSE;
  569. I16     AvioRet;
  570. static BOOL ReadGrpBuf(CAPT *, BOOL *);
  571. I16     DispAvioErr(char *pMsg);
  572.  
  573. VIDEO_SYNC  Syncs[2] =
  574. {
  575.     { 128, 128, 240, AVK_NTSC_FULL_RATE, AVK_PA_NTSC },
  576.     { 128, 153, 288, AVK_PAL_FULL_RATE,  AVK_PA_PAL  }
  577. };
  578.  
  579. // Initialize the AVIO summary header and use it to create an AVSS file.
  580. BOOL OpenAvioFile(char *pFileSpec)
  581. {
  582.     AVIO_VID_SUM FAR    *pVid;
  583.     AVIO_AUD_SUM FAR    *pAud;
  584.     VIDEO_SYNC      *pSync;
  585.  
  586.     if (!*pFileSpec)
  587.         return DispErr("OpenAvioFile", "No file spec");
  588.                 
  589.     // Clear out the Avio structure.       
  590.  
  591.     _fmemset((char FAR *)&Avio, 0, sizeof(Avio));
  592.  
  593.     // Initialize the structure.
  594.     Avio.SumHdrSize = sizeof(AVIO_SUM_HDR);
  595.     Avio.VidSumSize = sizeof(AVIO_VID_SUM);
  596.     Avio.AudSumSize = sizeof(AVIO_AUD_SUM);
  597.  
  598.     Avio.StrmCnt = 2;
  599.     Avio.VidCnt = 1;
  600.     Avio.AudCnt = 1;
  601.  
  602.     if ((AvioRet = AvioFileAlloc((AVIO_SUM_HDR FAR *)&Avio)) < 0)
  603.         return DispAvioErr("AvioFileAlloc");
  604.  
  605.     // Fill out the video stream substructure.
  606.     
  607.     pSync = &Syncs[CaptureSync];    // sync data (NTSC or PAL)
  608.  
  609.     pVid = Avio.VidStrms;
  610.  
  611.     pVid->StrmNum = 0;      // video stream number
  612.     pVid->Type = AVL_T_CIM;     // compressed data
  613.     pVid->SubType = AVL_ST_YVU; // packed data
  614.     pVid->StillPeriod = AVL_CIM_RANDOM_STILL;  // freq of still frames
  615.     pVid->xRes = pSync->xResVid << 1;      // x resolution
  616.     pVid->yRes = pSync->yResVid;           // y resolution
  617.     pVid->BitmapFormat = AVK_BM_9;         // bitmap format
  618.     pVid->FrameRate = pSync->FrameRate;    // frame rate
  619.     pVid->PixelAspect = pSync->PixelAspect;    // NTSC aspect ratio
  620.     pVid->AlgCnt = 1;              // only one algorithm
  621.     pVid->AlgName[0] = AVK_RTV_2_0;        // RTV 2.0 compression alg
  622.  
  623.     // Fill out the audio stream substructure.
  624.  
  625.     pAud = Avio.AudStrms;
  626.  
  627.     pAud->StrmNum = 1;          // audio stream number
  628.     pAud->LeftVol = 100;            // left channel volume = 100%
  629.     pAud->RightVol = 100;           // right channel volume = 100%
  630.     pAud->FrameRate = pSync->FrameRate; // frame rate
  631.     pAud->SamplesPerSecond = AUD_SAMPLE_RATE;  // audio samples-per-second
  632.     pAud->AudChannel = AVK_AUD_MIX;     // both speakers
  633.     pAud->AlgCnt = 1;           // number of algorithms 
  634.     pAud->AlgName[0] = AVK_ADPCM4;      // audio ADPCM4 algorithm
  635.  
  636.     // Now create the file with all standard AVSS headers.
  637.  
  638.     if ((AvioRet = AvioFileCreate((char far *)pFileSpec, 
  639.       (AVIO_SUM_HDR FAR *)&Avio, OF_CREATE)) < 0)
  640.         return DispAvioErr("AvioFileCreate");
  641.  
  642.     bAvioFileExists = TRUE;
  643.  
  644.     return TRUE;
  645. }
  646. // This function retrieves frames from the Group Buffers
  647. // in VRAM and writes them out to an AVSS file on disk.
  648. BOOL CaptureAvioData()
  649. {
  650.     static BOOL     bInUse = FALSE;
  651.     AVIO_FRM_HDR FAR    *pFrmHdr[2];    // frame header pointers
  652.                         // for video & audio
  653.     BOOL            bDataRead;
  654.     int         Ret;
  655.     U32         VidFrmSize, AudFrmSize;
  656.     WORD            Count;
  657.  
  658.     if (bInUse)
  659.         return TRUE;
  660.  
  661.     bInUse = TRUE;
  662.  
  663.     // Error if no buffers have been allocated.
  664.     if (!Vid.pBufHead || !Aud.pBufHead)
  665.         return DispErr("CaptureAvioData",
  666.             "NULL host RAM buffer pointer");
  667.  
  668.     Count = CAPTURE_LOOPS;
  669.  
  670.     do {
  671.         // Init the data-read flag
  672.         bDataRead = FALSE;
  673.  
  674.         if (!Vid.BufDataCnt)
  675.         {
  676.             if (!ReadGrpBuf(&Vid, &bDataRead))
  677.                 return FALSE;
  678.         }
  679.         if (!Aud.BufDataCnt)
  680.         {
  681.             if (!ReadGrpBuf(&Aud, &bDataRead))
  682.                 return FALSE;
  683.         }
  684.  
  685.         while (Vid.BufDataCnt && Aud.BufDataCnt)
  686.         {
  687.             pFrmHdr[0] = (AVIO_FRM_HDR FAR *)Vid.pBufCurr;
  688.             pFrmHdr[1] = (AVIO_FRM_HDR FAR *)Aud.pBufCurr;
  689.  
  690.             if ((Ret = AvioFileFrmWrite((AVIO_SUM_HDR FAR *)&Avio,
  691.                 pFrmHdr)) < 0)
  692.                 return DispAvioErr("AvioFileFrmWrite");
  693.  
  694.             VidFrmSize = (U32)sizeof(AVIO_FRM_HDR)
  695.                 + pFrmHdr[0]->StrmSize[0];
  696.             Vid.pBufCurr += (WORD)VidFrmSize;
  697.             Vid.BufDataCnt -= VidFrmSize;
  698.  
  699.             AudFrmSize = (U32)sizeof(AVIO_FRM_HDR)
  700.                 + pFrmHdr[1]->StrmSize[0];
  701.             Aud.pBufCurr += (WORD)AudFrmSize;
  702.             Aud.BufDataCnt -= AudFrmSize;
  703.         }
  704.     } while (bDataRead && Count--);
  705.  
  706.     bInUse = FALSE;
  707.     return TRUE;
  708. }
  709. // Read newly captured frames from an AVK Group Buffer
  710. // into one of the application's host RAM buffers
  711. static BOOL ReadGrpBuf(CAPT *pCapt, BOOL *pbDataRead)
  712. {
  713.     // Only refill the buffer if it is empty
  714.     if (!pCapt->BufDataCnt)
  715.     {
  716.         // Retrieve a buffer of frames.
  717.  
  718.         if ((AvkRet = AvkGrpBufRead(pCapt->hGrpBuf, HOST_BUF_SIZE, 
  719.           pCapt->pBufHead, &pCapt->BufDataCnt, AVK_ENABLE)) != OK)
  720.             return DispAvkErr(AvkRet, "AvkGrpBufRead");
  721.  
  722.         // Set data-read flag if we read any data.
  723.  
  724.         *pbDataRead = pCapt->BufDataCnt == (U32)0 ? FALSE : TRUE;
  725.  
  726.         // Point back to start of buffer.
  727.  
  728.         pCapt->pBufCurr = pCapt->pBufHead;
  729.     }
  730.     return TRUE;
  731. }
  732. // Update and lose an AVSS file using AVKIO.
  733. BOOL CloseAvioFile()
  734. {
  735.     if (bAvioFileExists == TRUE)
  736.     {
  737.         // Update the file's header with current information that
  738.         // AVKIO keeps in the Avio summary header.
  739.  
  740.         if ((AvioRet = AvioFileUpdate((AVIO_SUM_HDR FAR *)&Avio, 0)) < 0)
  741.             return DispAvioErr("AvioFileUpdate");
  742.  
  743.         // Close the file.
  744.  
  745.         if ((AvioRet = AvioFileClose((AVIO_SUM_HDR FAR *)&Avio)) < 0)
  746.             return DispAvioErr("AvioFileClose");
  747.  
  748.         bAvioFileExists = FALSE;
  749.     }
  750.     return TRUE;
  751. }
  752.  
  753.  
  754.